/*
 * File:   main.cpp
 * Author: cyril
 *
 * Created on 10 décembre 2012, 09:33
 */
#include<iostream>
#include <stdio.h>
#include <mpi.h>
#include "const.h"

using namespace std;

int main(int argc, char* argv []) {
    int compteur, myrank, nombre,nbr_voisin_temp;
    int voisin[8];
    int pas;
    float temperature, temperature_voisin, total_temperature_voisin;
    MPI_Comm parent;
    MPI_Status etat;
    MPI_Request request;
    MPI_Init(&argc, &argv);
    MPI_Comm_get_parent(&parent);
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
    MPI_Comm_size(MPI_COMM_WORLD, &nombre);

    // Reste bloqué en attente d'un int du coordinateur
    if (parent == MPI_COMM_NULL) {
        printf("Fils %d : calc : Pas de pere !\n", myrank);
    } else {
        // Réception du  père
        MPI_Recv(voisin, 8, MPI_INT, 0, 0, parent, &etat);
        printf("Fils %d : calc : Reception du pere !\n", myrank);
        // Réception de la température
        MPI_Recv(&temperature, 1, MPI_FLOAT, 0, 0, parent, &etat);
        printf("Reception de sa temperature : %f !\n", temperature);

        // Réception du pas du coordinateur
        MPI_Recv(&pas, 1, MPI_INT, (nombre-1), 0, MPI_COMM_WORLD, &etat);
        
        // Si le int est supérieur à 0 c'est le numéro du pas de simulation à traiter
        while (pas > 0) {
		printf("Pas %d - Voisin %d \n", pas,myrank );
		nbr_voisin_temp=0;
		total_temperature_voisin=0;
            // Si le int est supérieur à 0 ...
            // ... il envoie de manière asynchrone sa température à ses voisins
            for (int i = 0; i < NBVOISINS; i++) {
                // S'il y a un voisin
                if (voisin[i] != -1){			
                    // Envoi température à ses voisins
                    MPI_Isend(&temperature, 1, MPI_FLOAT, voisin[i], 0, MPI_COMM_WORLD, &request);
                    printf("%d - Envoi température au voisin %d : %f \n", myrank,voisin[i], temperature);
                    
                }
            }


	for (int i = 0; i < NBVOISINS; i++) {
			// S'il y a un voisin
			if (voisin[i] != -1){
				nbr_voisin_temp++;
			   
			    // Réception des températures des voisins
			    
			    MPI_Irecv(&temperature_voisin, 1, MPI_FLOAT, voisin[i], 0, MPI_COMM_WORLD, &request);
			    MPI_Wait(&request, &etat);
			    total_temperature_voisin += temperature_voisin;
			    printf("%d - Temperature du voisin %d : %f \n", myrank, voisin[i], temperature_voisin);
			}
                        else total_temperature_voisin += 35 ;    // Si pas de voisin donc temp de l'air ambiant
		}
            // Faire la moyenne avec lui même et se met à jour
	    temperature = (temperature + total_temperature_voisin) / (NBVOISINS+1);
            printf("%d - TempTotal %f - Nouvelle temperature (moyenne) : %f \n", myrank,total_temperature_voisin, temperature);

            // Envoi la moyenne au coordinateur
            
	    MPI_Isend(&temperature, 1, MPI_FLOAT, (nombre - 1), 0, MPI_COMM_WORLD, &request);
	    printf("%d -Envoi de la moyenne au coord \n", myrank);

            // Attendre le prochain pas
            MPI_Recv(&pas, 1, MPI_INT, (nombre-1), 0, MPI_COMM_WORLD, &etat);
        }

        // Si le int == -1
        if(pas == -1){
            // Il affiche un message de fin
            printf("Fils %d : Fin du calculateur \n", myrank);
            // Se termine avec le code d'erreur 0
        }
        
    }

    // Fin MPI
    MPI_Finalize();
    return 0;
}
